// Java的数据类型与运算符
// 1. 变量和类型
// 变量 指的是 程序运行时 的 可变的量，相当于开辟一块内存空间来保存一些数据
// 类型 则是 对 变量的种类 进行了 划分，不同的类型 的 变量 具有不同特性

// 我们所讨论的"变量"主要 和 我们的"内存"这样的硬件设备密切相关
// 我们先来讲讲变量。
// 变量就像一个个大小不一的盒子（类型不同的变量），盒子的空间里面装着不同的宝藏，并且盒子里的宝藏是可以进行替换(覆盖)的，只要放得下。如果放不下，咱就不要它。
// 也就是说 不同类型的变量的空间 存储的数据 都是不同的,且变量的值是可以改变的

// 而存储的空间从何而来？
// 内存
// 打个比方
//  内存 就像 一个长长的街道（内存条），街道上住着形形色色的人（各种各样的变量）
// 就好比 类型不同 值相同 且变量不同 的数据[两个年纪相同的人，但是，是两个人不是一个人，也不是一个家庭的成员 char a = 10；int b = 10；]
// 和 类型相同值不同  且变量不同 的数据（生在同一个家庭，有兄弟姐妹，他们独特的存在。 int a =10；int b =20；） 
// 和 类型和值都相同  且变量不同 的数据(你可以认为就是性别，外貌 都一样的人，但他们名字不一样，确确实实是两个人，int a=0;int b =0;)
// 和 类型和值都不同  且变量不同 的数据（你可以认为是两个完全不搭边的人，float a=3.14；int b = 5；）
// 变量 就好比 一个人的唯一性，是不可重复或分裂，在程序中一个变量是不可以被重复定义的，在现实生活中，你总不能说人会分身吧。
// 而且变量的存储的数据和数据的类型 都是可以被改变的，唯一不变的就是变量本身（int a；a就是变量本身），人也是一样的，可以改变自己的，每个年龄阶段的自己都是不同，外貌，年龄都是不同的。唯一不变的就是这个人，他不可能变成另一个人，取代别人的存在（这个别杠，少看点剧）
// 只要是个人都有自己的家（变量都有自己的空间）,家是有门牌号的，而 门牌号 就相当于 变量空间的地址
// 内存就好比是这一条街道所有人的信息的汇总

// 切回实际，真正想要理解内存，需要理解 冯诺依曼 体系,因为现在的计算机都是以这个体系来建立我们逻辑关系的
// 小常识： 现代计算机之父 就是 约翰.冯.诺依曼。又是一个聪明绝顶的人
// 冯诺依曼体系 由五个部分组成
// 1、输入设备，2、输出设备，3、外存储器，4、内存储器，5、运算器和控制器（两者组成的，也就是所谓的CPU）
// 结构图 见图1
// 1,2就不用我解释了，我们来讲讲 外储存器 和 内存储器 有何区别？
// 举个列子 
// 买手机，商家可能会问你 你是要 8G+258G 还是 4G+64G 等等。
// 见图2
// 我们可以看到两块内存（小的内存，大的外存），我们都是 小一点的内存越大，玩游戏越顺畅。后面大的那个内存，说明你可以存很多数据到手机里，如果你是258的，都不够用，我想说汝分享否？
// 有的人会说，为什么我苹果的内存（运行内存）没有 安卓的大，玩同一个游戏，为什么它比我卡？
// 因为 苹果手机的每一个部件都是为苹果手机专门制造设计的，所以系统之间的兼容性很强，所以在玩游戏的时候，所占内存较小
// 而安卓机，就是一个组装机，懂得都懂，一个手机可能有几个厂家的部件组装而成，所以兼容性不是很好，所以在玩游戏的时候，所占内存较大
// 说白了就是，苹果房子的每一块转都是无缝链接，每一块砖的大小形状都是相同的，所以墙面光滑如玉（原装就是强[贵]）（打游戏，6的飞起）。
// 而安卓房子，就像是每一个砖之间是存在间隔（系统不兼容，导致内存有所浪费），再加上每一块砖的大小形状有着一些或很大的差别（又会占用一些内存的空间），导致墙面不光滑（卡的飞起，成为甩锅的对象）
// 当然国产机现在越做越好（贵）[好 == 贵].

// 电脑的内存（运行内存）见图3


// 再来说说 后面的外存，见图4



// CPU当中 运算器（逻辑运算）和  控制器（控制程序的运行【怎么运行，从哪里运行】 和 停止 【停止的条件，停止】，停止之后又该怎么做？）
// 这里我们不做深究，我们只是在 了解 内存的过程中 了解一下 冯洛伊曼体系 ，其重点是内存储器，也就是我们的内存。

// 总结： 变量 就是存储在 内存（内存储器【硬件】）当中，当变量的类型不一样，存储的数据也就不一样。它所占内存大小就不一样。
// 学了C的，都知道，变量在程序运行时，才在内存中申请空间，程序结束之后，要将空间还给 内存。
// 所以 变量的空间的创造和销毁（回收），都与我们的内存储器【硬件】有这密切的关系
// 回到我们的最初的标题，"变量"主要和我们的 "内存"这样的硬件设备密切相关




// 1.1 整形变量（ 4 byte）

// 基本语法格式
// int 变量名 = 初始值;


// 代码示例
// public class DataTypeAndOperator{
// 	public static void main(String[] args){
// 		int num = 10;// 定义一个整形变量，就相当于有一个箱子是a，它的类型int，存储的数据是 整数 10
// 		/*
//              另外注意 在Java中，int 就是 4个字节 的大小,与操作系统是多少位无关，这一点请牢记。
//              这是Java中的一个特点：可移植性强，就是 不管你的电脑是多少位操作系统，你把我的字节码文件拿过去，都可以跑起来
// 		*/
//         System.out.println(num);// （这里）直接放入你想要输出打印的变量，就OK了，没有像C一样，有打印格式要求
        
//         // 如果还是像 C 一样也可以，如下
//         System.out.printf("%d\n",num);

// 	}//效果图5，在这里跟大家回顾上一篇博客的内容
// 	//java一共有三种打印方式
// 	//System.out.println("打印换行，这种打印方式用的最多");
// 	//System.out.print("打印不换行");
// 	//System.out.printf("跟C语言一样，以格式化的形式进行输出。这种打印方式用的最少");
// }




// 字节，见 图 6


// 整形变量的取值范围
// 提醒：在 Java中，int 是没有无符号类型的（unsigned int），统一是 有符号的int（signed int），就是 有符号数【正负数】，
// 也就意味着我们的数值转化为二进制时，最高位永远都是符号位
// 例子
// int 为 4 byte，即 32bit位,即 32位二进制数
//  8 bit = 1 byte; 1024 byte = 1 kb; 1024 kb = 1mb; 1024 mb = 1gb; 1024 gb = 1 tb; 1024 tb = 1pb.
// 最高位为符号位，那么剩下的31位，都是数值位,就是能表示出 2^31 个数字
// 最高位【符号位】为 0，表示为正，数值位全部取1，得到最大值【2^31-1，因为0也算一个数字了，所以它能表达的最大值，就是 能表达数字的个数 减去一个1.（照理说是从1算起的，那么就是2^31），所以我们要减一】（图9,图11）
// 最高位【符号位】为 1，表示为负，数值位全部全1，得到最小值【-2^31,这个就是从-1算起，所以是-2^31】（图10）

//那么在 Java中 如何求 取值范围的最大值和最小值?

//  在此之前，我们需要 integer 是什么？
//  int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类，Integer是java为int提供的封装类。
// 小知识带你，除了 int 和 char，的封装类分别是 Integer，Character 之外
// 其它 6 个原始数据类型 都是首字符大写
// 8 个原始数据类型： byte(1) boolean[布尔类型](1) char(2) short(2) int(4) float(4) double(8) long(8),
//  int的默认值为0，而Integer的默认值为null
    
//     即Integer可以区分出未 未赋值 和 值为0 的区别，int则无法表达出未赋值的情况，例如，要想表达出 没有参加考试 和 考试成绩为0 的区别
//     则只能使用 Integer

//     另外，Integer提供了多个与整数相关的操作方法，例如，将一个字符串转换成整数，Integer中还定义了表示整数的最大值和最小值的常量。

// int的默认值为0，而Integer的默认值为null，程序如下：
// public class DataTypeAndOperator{
// 	public static void main(String[] args) {
// 		int a;
// 		System.out.println(a);
// 	 } 程序出错，不应该输出为 0吗？
// 	 因为在 Java中 一个局部变量，没有进行初始化赋值，那么就不能够使用它，如果运行，程序会报错。
// 	 这里体现出 Java的安全性
// 	 ps：在Java中是没有全局变量的，这点请记住
// }
// 另外注意一点，在方法（main方法）中，定义的量叫做变量
// 在类的内部，方法的外部的量，叫做属性（又称 成员变量），
// 比如说  我就在  DataTypeAndOperator 的花括号后面建立 int a 的变量
// 这时，a就是成员变量（属性）,它的默认值就是 0。



// 现在我们来在Java中求 int 类型 所能存储最大值和最小值
public class DataTypeAndOperator{
	public static void main(String[] args){
		System.out.println(Integer.MAX_VALUE);
		System.out.println(Integer.MIN_VALUE);
	}
}// 效果图见 7


// 最大值+1，最小值-1，会导致数值溢出（相当于碗就这么点大，容量有限，你非要装，肯定是会溢出的），那么效果如何？
// 程序如下：
public class DataTypeAndOperator{
	public static void main(String[] args){
		System.out.println(Integer.MAX_VALUE+1);
		System.out.println(Integer.MIN_VALUE-1);
	}
}// 效果图见 8
从 效果图 和 圆形图 可以看出，正数 0~2^31-1，负数 -1 ~ -2^31. -2^31 代替了 2^31的位置，从而形成了一个圆形范围（取值循环）
最大值加一，取得最小值；最小值减一，取得最大值



变量的命名：小驼峰形式 intMax，第一词的首字符小写，后面词的首字符大写（见附图 驼峰）
 在Java中 标识符由数字、字母、下划线、$，组成
表示开头不能是数字（ int a2；right，  int 2a；error）
注意 $ 和 下划线， 虽然可以这么写 int $a，int _a, 但不建议(别给别人挖坑，保持良好代码习惯)。
举个例子，有一个二货这么写 int ______a=0; ，你告诉我这有几个下划线？，所以别这么写 


// 其实在Java还有一个地方，特别拐。
public class DataTypeAndOperator{
	public static void main(String[] args) {
		int 钱 = 10;
		System.out.println(钱);
	}
}// 效果图见12
因为 Java 是Unicode字符集，它包含ASCII码字符集，拉丁文，中文 等等...
所以 在 Java 中 能以中文作为变量。
但是最好不要这么写，有点过了。。。

注意事项
1. int 表示变量的类型是一个整形，另外 在 Java中 int 是没有无符号类型的（unsigned int），统一是 有符号的int（signed int）
2. 变量名是变量的标识（int a，a就是变量名），后续都是通过这个名字来使用变量
3. Java 中 = 表示赋值，意思是给变量设置一个初始值。（和数学不一样，数学里是等于的意思）
4. 初始化操作时可选的，但是 建议 创建变量的时候都显式初始化。（尤其是局部变量，不初始化，程序会报错）
5. 最后不要忘记分号，否则会编译失败
6. // 表示注释，注释作为代码的解释说明部分，不参与编译运行。



// 1.2长整形变量（长整形：long  8 byte）
基本语法格式
long 变量名 = 初始值;
注意  在Java中是没有long long类型的。

long : 8 byte == 64 bit
除去一个符号位，还剩63位，也就是说 取值范围为 -2^63 ~ 2^63-1(附图从 上篇文章提取)
long类型的数据的最大值为 2^63-1,最小值为 -2^63
//  程序如下

    public class DataTypeAndOperator{
    	public static void main(String[] args) {
    		long a = 10l;// 10 后面加一个 大写的 L ，表示long类型的数据。
    		// 如果是小写 int a =10l，就不明显，看起来 跟 数字 1 一模一样。
    		// 代码习惯！！！
    		// 所以 L 还是要大写
    		long long b =10;// long long 类型是不存在的，图14
    		System.out.println(Long.MAX_VALUE);
    		System.out.println(Long.MIN_VALUE);
    	}
    }//效果图，见 13
注意事项:
1. 基本语法格式和创建 int 变量基本一致, 只是把类型修改成 long
2. 初始化设定的值为 10L , 表示一个长整型的数字. 小写的 l，不建议写。
3. 使用 10 初始化也可以, 10 的类型是 int, 10L 的类型是 long, 使用 10 L  更好一些.
Java 中 long 类型占 8 个字节. 表示的数据范围 -2^63 -> 2^63-1




// 1.3 双精度浮点型变量(8 byte)
基本语法 
double 变量名 = 初始值；

代码示例

public class DataTypeAndOperator{
	public static void main(String[] args) {
		double d = 10.1;
		System.out.println(d);
	}// 效果图 15
}


//拓展代码
public class DataTypeAndOperator{
	public static void main(String[] args) {
		int a =1;
		int b =2;
		System.out.println(a/b);//照理 结果是0.5
	// 但是在Java中整数除以整数，结果只能是整数。
		//结果取 0.5 整数位 0
	}// 效果图 16
}


// 那么我么想得到 0.5，该怎么写？
// 代码如下
public class DataTypeAndOperator{
	public static void main(String[] args) {
		double a =1.0;// 占 8个字节
		double b =2.0;

		// 如果这样写呢？
		// int a = 1.0;小数占8个字节，int 肯定是 放不下的
		// int b = 2.0;
		System.out.println(a/b);
		//只有 a 和 b都是小数的情况下，结果才是 我们想要的 0.5
	
	}// 效果图 17
}



public class DataTypeAndOperator{
	public static void main(String[] args) {
		double a =1.1;// 占 8个字节
		double b =2.0;
		System.out.println(a*a);
		// 照理说 结果应该为 1.21
	   // 但是结果为 1.2100000000000002，后面多了一个 2，这是为什么呢？
		// 因为在程序里，小数是没有精确的数字的
		// 也就是说 小数本身是没有一个精确的数字的。它只能精确到几位

		// float类型，只能精确到小数点后 6 位
		// double类型，只能精确到小数点后 16 位
	}// 效果图 18




//1.4 单精度浮点型变量(4 byte)
基本格式：
float 变量名 =初始值;

代码示例
public class DataTypeAndOperator{
	public static void main(String[] args) {
		float a =1.0f;// 占 4 个字节

		// 为什么不这样写？
		//float a = 1.0;
	    // 因为小数是默认 占 8 字节，也就是默认 double类型	
	    // 你需要知道 Java是一门强势语言，赋值一定要类型相同，否则代码进行编译时，是不会通过的，会报错。
		// 所以在 java 当中，对 单精度浮点型，也就是对float类型的变量，进行赋值时，小数后面一定要加上 小写 f 或 大写 F
		// 12.5f 或 12.5F 这样写，就表明了 小数 12.5 是一个单精度浮点型数据，而非双精度浮点型数据
		System.out.println(a);

	}// 效果图 19，20
}

注意：
float 类型在 Java 中占四个字节, 同样遵守 IEEE 754 标准. 由于表示的数据精度范围较小, 一般在工程上用到浮点数都
优先考虑 double, 不太推荐使用 float



//1.5 字符类型变量( 2 byte)
基本格式：
char 变量名 = 初始值;


代码示例
public class DataTypeAndOperator{
	public static void main(String[] args) {
		char a ='w';
		char b = '强';
		System.out.println(a);
        System.out.println(b);
	}// 效果图 21 ,由效果图可知 char 类型能够存的下 汉字
	// 一个汉字占 2 个字节，也就意味着 char 在 Java 当中，所占内存大小为 2 字节
}


//代码2
public class DataTypeAndOperator{
	public static void main(String[] args) {
		char a =97;// 97 是 字符 a 的 ASCII 码值
		System.out.println(a);

	}
// 效果图 22 ,由图可知 在 Java 中，将 整数 赋给char类型的变量，Java会将 整形数据 转换成 ASCII码值
	// 再将其打印，其结果是 ASCII码值 所对应的 字符
	
}

注意事项:
1. Java 中使用 单引号 + 单个字母 的形式表示字符字面值.
2. 计算机中的字符本质上是一个整数. 在 C 语言中使用 ASCII 表示字符
而 Java 中使用 Unicode 表示字符. 因此一个字符占用两个字节, 表示的字符种类更多, 包括中文.





//1.6 字节类型变量（相当于 C语言里面的char，内存大小 1 byte）
基本语法格式：
byte 变量名 = 初始值


public class DataTypeAndOperator{
	public static void main(String[] args) {
		byte a =9;

		// 另外 和 int 它们一样，赋值超过它的取值范围，程序会报错
		// 1 byte = 8 bit
		// 除去符号位，取值范围为 -2^7 ~ 2*7-1(-128~127)
        byte b = 130;
		System.out.println(b);// 效果图见 24
		// 由图可知，130 超出去 byte 能存储的值，系统会认为该值的类型 是 其他类型，且所占字节比它大。
		// 两者之间无法进行赋值

		// 注意: 在Java中，所有数据，都是这样，拥有属于它们自己的取值范围， 一个类型的变量，只能存储该类型的取值范围以内的值
		// 超出了，我就存不了。
		// 就是说 多一分不行，少一分可以，因为我放得下
		// 类型 所占字节大的，可以放下 比它 所占字节要小的类型的值
		// 就是说 一个类型的取值范围比另一个类型的取值范围 要大时， 取值范围大的类型，可以存放 取值范围小的类型的所有值
		// 说白了 就是 大吃小，小吃不下大。



		System.out.println(a);

	}
// 效果图 23
	
}

另外 提示一下， 在Java当中，是没有sizeof 这种操作符的。
就是说 类型所占字节的大小，你需要自己记住

注意事项:
 1. 字节类型表示的也是整数. 只占一个字节, 表示范围较小 ( -128 -> +127 )
 2. 字节类型和字符类型互不相干


// 1.7 短整型变量(2 byte)
基本语法格式
short 变量名 = 初始值;
 
 代码示例

public class DataTypeAndOperator{
	public static void main(String[] args) {
		short a = 2;
		// 2 字节 == 16 byte
		// 出了符号位
		// 它的取值范围为 -2^15 ~ 2^15-1( -32768 ~ 32767)
		System.out.println(a);
	}
}